#ifndef GSMARTPOINTER_H_INCLUDED
#define GSMARTPOINTER_H_INCLUDED

class CGRefCount
{
public:
  CGRefCount() { m_refs = 0; }
  ~CGRefCount() { }
  void AddRef() { CGAutoLock lock(&m_cs); m_refs++; }
  gint Release() { CGAutoLock lock(&m_cs); return --m_refs; }

private:
  gint m_refs;
  CGCriticalSectionWrapper m_cs;
};

template <typename T> class CGSmartPtr
{
public:
  CGSmartPtr() : m_data(NULL), m_ref(NULL)
  {
    m_ref = new CGRefCount;
    m_ref->AddRef();
  }

  CGSmartPtr(T *data) :	m_data(data), m_ref(0)
  {
    m_ref = new CGRefCount;
    m_ref->AddRef();
  }

  CGSmartPtr(const CGSmartPtr<T> &ptr) : m_data(ptr.m_pData), m_ref(ptr.m_rRef)
  {
    if(m_ref)
      m_ref->AddRef();
  }

  CGSmartPtr(const CGSmartPtr<T> *ptr) : m_data(NULL), m_ref(NULL)
  {
    if(ptr)
    {
      m_data = ptr->m_data;
      m_ref = ptr->m_ref;
      if(m_ref)
        m_ref->AddRef();
    }
  }

  virtual ~CGSmartPtr() { Release(); }
  T & operator* () { return *m_data; }
  T * operator-> () { return m_data; }

  CGSmartPtr<T> & operator= (const CGSmartPtr<T> &ptr)
  {
    if(this == &ptr) return *this;
    Release();
    m_data = ptr.m_data;
    m_ref = ptr.m_ref;
    AddRef();
    return *this;
  }

  bool operator== (T *ptr) const { return m_data == ptr; }
  bool operator!=(T* ptr) const { return m_data != ptr; }
  operator T*() { return m_data; }
  void AddRef() { if(m_ref) m_ref->AddRef(); }
  void Release()
  {
  if(m_ref && m_ref->Release() == 0)
  {
    if(m_data)
      delete m_data, m_data = NULL;
    delete m_ref, m_ref = NULL;
  }
}

protected:
  T *m_data;
  CGRefCount *m_ref;
};

#endif // GSMARTPOINTER_H_INCLUDED
